package com.fredhat.gwt.xmlrpc.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * A simple proxy servlet that repeats request and response messages to an external server.
 * That server URL is defined in the <i>hostURL</i> init parameter in web.xml.  This is used
 * as an example of how to bypass the Same Origin Policy that is enforced on most modern
 * web browsers.
 * @author Fred
 *
 */
public class ProxyServlet extends HttpServlet {
	private static final int HTTP_OK = 200;
	private static final String HOST_URL_PARAMETER = "hostURL";
	
	public void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException {
		String hostURL = this.getServletConfig().getInitParameter(HOST_URL_PARAMETER);
		if (hostURL == null) {
			throw new ServletException("Required init parameter [hostURL] must be set");
		}
		
		// Fetch the POST request content 
		String requestContents = null;
		try {
			requestContents = getRequestContents(request);
		} catch (IOException e) {
			throw new ServletException(e);
		}

		// Use the apache commons HTTP client library to repeat the request to
		// an external server.
		HttpResponse proxyResponse = getResponse(hostURL, requestContents);
		if (proxyResponse.getStatusLine().getStatusCode() != HTTP_OK) {
			throw new ServletException("Bad status code from server: "+
					proxyResponse.getStatusLine());
		}
		
		HttpEntity entity = proxyResponse.getEntity();
		InputStream is = null;
		if (entity != null) {
			try {
				is = entity.getContent();
				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
				String str;
				PrintWriter out = response.getWriter();
				while ((str = reader.readLine()) != null) {
					out.println(str);
				}
			} catch (Exception e) {
				throw new ServletException(e);
			} finally {
				if (is != null)
					try {
						is.close();
					} catch (IOException e) {}
			}
		}
	}
	
	private String getRequestContents(HttpServletRequest request) throws IOException {
		StringBuffer reqBody = new StringBuffer();
		BufferedReader reader = request.getReader();
		String str;
		while ((str = reader.readLine()) != null) {
			reqBody.append(str);
		}

		return reqBody.toString();
	}
	
	private HttpResponse getResponse(String hostURL, String requestContents) 
			throws ServletException {
		HttpClient client = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(hostURL);
		HttpResponse httpResponse = null;

		try {
			httpPost.setEntity(new StringEntity(requestContents));
		} catch (UnsupportedEncodingException e) {
			throw new ServletException(e);
		}
		try {
			httpResponse = client.execute(httpPost);
		} catch (Exception e) {
			throw new ServletException(e);
		}

		return httpResponse;
	}
}
